﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using KC.Framework;
using KC.Framework.Base;
using Microsoft.EntityFrameworkCore;

namespace KC.Domain.Core.IRepository
{
    public interface IDbRepository<T> : IRepository<T> where T : EntityBase
    {
        #region 属性
        /// <summary>
        ///     获取 当前实体的查询数据集
        /// </summary>
        IQueryable<T> Entities { get; }

        IUnitOfWork<DbContext> UnitOfWork { get; }
        #endregion

        #region Add
        int Add(IEnumerable<T> entities, bool isSave = true);
        //bool Add(T entity, bool isSave = true);
        Task<bool> AddAsync(IEnumerable<T> entities, bool isSave = true);
        Task<bool> AddAsync(T entity, bool isSave = true);
        #endregion

        #region Exist
        bool ExistByFilter(Expression<Func<T, bool>> predicate);
        Task<bool> ExistByFilterAsync(Expression<Func<T, bool>> predicate);
        #endregion

        #region Search
        T FindByFilter(Expression<Func<T, bool>> predicate);
        Task<T> FindByFilterAsync(Expression<Func<T, bool>> predicate);
        T FindById(params object[] keyValues);
        Task<T> FindByIdAsync(params object[] keyValues);

        //IList<T> Find(Expression<Func<T, bool>> predicate);
        //IList<T> Find<K>(Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, bool ascending = true);
        //IList<T> FindAll();
        //IList<T> FindAll<K>(Expression<Func<T, K>> keySelector, bool ascending = true);
        Task<IList<T>> FindAllAsync();
        Task<IList<T>> FindAllAsync<K>(Expression<Func<T, K>> keySelector, bool ascending = true);
        Task<IList<T>> FindAsync(Expression<Func<T, bool>> predicate);
        Task<IList<T>> FindAsync<K>(Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, bool ascending = true);

        IList<T> FindPagenatedList<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, bool ascending = true);
        IList<T> FindPagenatedList<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, string sortProperty, bool ascending = true);
        Task<IList<T>> FindPagenatedListAsync<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, bool ascending = true);
        Task<IList<T>> FindPagenatedListAsync<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, string sortProperty, bool ascending = true);
        Tuple<int, IList<T>> FindPagenatedListWithCount<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, bool ascending = true);
        Tuple<int, IList<T>> FindPagenatedListWithCount<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, string sortProperty, bool ascending = true);
        Task<Tuple<int, IList<T>>> FindPagenatedListWithCountAsync<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, bool ascending = true);
        Task<Tuple<int, IList<T>>> FindPagenatedListWithCountAsync<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, string sortProperty, bool ascending = true);
        #endregion

        #region Count
        int GetRecordCount();
        Task<int> GetRecordCountAsync();
        #endregion

        #region Modify
        //bool Modify(T entity, bool isSave = true);
        int Modify(IEnumerable<T> entities, string[] properties = null, bool isSave = true);
        bool Modify(T entity, string[] properties, bool isSave = true);

        Task<int> ModifyAsync(IEnumerable<T> entities, string[] properties = null, bool isSave = true);
        Task<bool> ModifyAsync(T entity, bool isSave = true);
        Task<bool> ModifyAsync(T entity, string[] properties, bool isSave = true);
        #endregion

        #region Remove & SoftRemove
        
        //int Remove(IEnumerable<T> entities, bool isSave = true);
        bool Remove(object id, bool isSave = true);
        //bool Remove(T entity, bool isSave = true);
        //bool RemoveAll();
        int Remove(Expression<Func<T, bool>> predicate, bool isSave = true);
        Task<bool> RemoveAllAsync();
        Task<int> RemoveAsync(Expression<Func<T, bool>> predicate, bool isSave = true);
        Task<int> RemoveAsync(IEnumerable<T> entities, bool isSave = true);
        Task<bool> RemoveAsync(object id, bool isSave = true);
        Task<bool> RemoveAsync(T entity, bool isSave = true);

        int SoftRemove(Expression<Func<T, bool>> predicate, bool isSave = true);
        int SoftRemove(IEnumerable<T> entities, bool isSave = true);
        bool SoftRemove(object id, bool isSave = true);
        bool SoftRemove(T entity, bool isSave = true);
        Task<int> SoftRemoveAsync(Expression<Func<T, bool>> predicate, bool isSave = true);
        Task<int> SoftRemoveAsync(IEnumerable<T> entities, bool isSave = true);
        Task<bool> SoftRemoveAsync(T entity, bool isSave = true);
        #endregion

        #region 执行数据库脚本
        bool ExecuteSql(string query, params object[] parameters);
        Task<bool> ExecuteSqlAsync(string query, params object[] parameters);
        List<K> SqlQuery<K>(string query);
        #endregion
    }


}
